﻿using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;

namespace Knowledge.EF.Back.Helpers
{
    public interface IJWTService
    {
        /// <summary>
        /// 根据用户名获取token
        /// </summary>
        /// <param name="UserName"></param>
        /// <returns></returns>
        string GetToken(string UserName);
    }

    /// <summary>
    /// 生成JWT的service类
    /// </summary>
    public class JWTService : IJWTService
    {
        private readonly IConfiguration _configuration;
        /// <summary>
        /// 在构造函数中注入configuration以拿取appsettings.json中的内容
        /// </summary>
        /// <param name="configuration"></param>
        public JWTService(IConfiguration configuration)
        {
            this._configuration = configuration;
        }


        /// <summary>
        /// 根据用户名获取token
        /// </summary>
        /// <param name="UserName"></param>
        /// <returns></returns>
        public string GetToken(string UserName)
        {
            //注：下面调用方法都是使用了默认的header
            //初始化payload
            Claim[] claims = new[]
            {
                new Claim(ClaimTypes.Name,UserName),
                new Claim("name","zhangsan"),
                new Claim("time",DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"))
            };
            //生成对称秘钥
            SymmetricSecurityKey key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["secret"]));
            //初始化签名凭证
            SigningCredentials creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
            /**
             *  Claims (Payload)
                Claims 部分包含了一些跟这个 token 有关的重要信息。 JWT 标准规定了一些字段，下面节选一些字段:
                iss: jwt签发者
                sub: jwt所面向的用户
                aud: 接收jwt的一方
                exp: jwt的过期时间，这个过期时间必须要大于签发时间
                nbf: 定义在什么时间之前，该jwt都是不可用的.
                iat: jwt的签发时间
                jti: jwt的唯一身份标识，主要用来作为一次性token,从而回避重放攻击。
                除了规定的字段外，可以包含其他任何 JSON 兼容的字段。
             * */
            var token = new JwtSecurityToken(
                issuer: _configuration["issuer"],//设置签发者
                audience: _configuration["audience"],//设置接收者
                claims: claims,//设置payload
                expires: DateTime.Now.AddMinutes(5),//5分钟有效期
                signingCredentials: creds);//初始化安全令牌参数
            //输出token
            string returnToken = new JwtSecurityTokenHandler().WriteToken(token);
            return returnToken;
        }
    }
}
